/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#include "Ucop/DBC/DBCFileLoader.h"
using namespace Ucop::Util;


namespace Ucop {
namespace DBC {

	DBCFileLoader::DBCFileLoader(void)
	{

	}

	DBCFileLoader::~DBCFileLoader(void)
	{

	}

	bool DBCFileLoader::Load(const char* _Filename, const char* _Fmt)
	{
		std::uint32_t _Header;
		delete[] _Mydata;

		FILE* f = fopen(_Filename, "rb");
		if (!f) { return false; }

		if (fread(&_Header, 4, 1, f) != 1)                       // Number of records
		{
			fclose(f);
			return false;
		}

		endianConvert(_Header);
		if (_Header != 0x43424457)                               //'WDBC'
		{
			fclose(f);
			return false;
		}

		if (fread(&_MyrecordCount, 4, 1, f) != 1)                  // Number of records
		{
			fclose(f);
			return false;
		}
		endianConvert(_MyrecordCount);

		if (fread(&_MyfieldCount, 4, 1, f) != 1)                   // Number of fields
		{
			fclose(f);
			return false;
		}
		endianConvert(_MyfieldCount);

		if (fread(&_MyrecordSize, 4, 1, f) != 1)                   // Size of a record
		{
			fclose(f);
			return false;
		}
		endianConvert(_MyrecordSize);

		if (fread(&_MystringSize, 4, 1, f) != 1)                   // String size
		{
			fclose(f);
			return false;
		}
		endianConvert(_MystringSize);

		_MyfieldsOffset = new std::uint32_t[_MyfieldCount];
		_MyfieldsOffset[0] = 0;
		for (std::uint32_t _I = 1; _I < _MyfieldCount; ++_I)
		{
			_MyfieldsOffset[_I] = _MyfieldsOffset[_I - 1];
			if (_Fmt[_I - 1] == 'b' || _Fmt[_I - 1] == 'X')         // byte fields
			{
				_MyfieldsOffset[_I] += 1;
			}
			else                                                // 4 byte fields (std::int32_t/float/strings)
			{
				_MyfieldsOffset[_I] += 4;
			}
		}

		_Mydata = new unsigned char[_MyrecordSize * _MyrecordCount + _MystringSize];
		_MystringTable = _Mydata + _MyrecordSize * _MyrecordCount;

		if (fread(_Mydata, _MyrecordSize * _MyrecordCount + _MystringSize, 1, f) != 1)
		{
			fclose(f);
			return false;
		}

		fclose(f);
		return true;
	}

}}